package com.serial.comm.core.utils;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.serial.comm.core.constants.SystemConstants;
import com.serial.comm.core.exception.*;
import com.serial.comm.core.exception.enums.ResponseCodeEnum;
import org.apache.commons.lang3.StringEscapeUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.CollectionUtils;

import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import static com.serial.comm.core.constants.TelegramConst.*;

public class TelegramUtils {

    public static Logger log = LoggerFactory.getLogger(TelegramUtils.class);


    /**
     * 传入一帧完整的电报 产生所有有效电报拆分后的列表
     *
     * @param source
     * @return
     */
    public static Pair<String, List<String>> matchValidTelegram(String source) {
        log.info(">>>>>>开始提取原始报文中的有效电报");
        List<String> tgList = new ArrayList<>();
        String error = "";
        //正则表达式
        String pattern = "=HEADER[\\s\\S]+?LAST";
        Pattern r = Pattern.compile(pattern);
        Matcher m = r.matcher(source);
        int count = 0;
        while (m.find()) {
            int to = m.end(0);
            int from = m.start(0);
            StringBuilder sb = new StringBuilder(source);
            String one = sb.substring(from, to);
            tgList.add(one);
            count++;
        }
        log.info(">>>>>>共匹配到 {} 段有效电报", count);
        if (CollectionUtils.isEmpty(tgList)) {
            error = "未匹配到有效电报";
        }
        return Pair.makePair(error, tgList);

    }


    /**
     * 从头部信息中提取出 recDate 字符串信息
     *
     * @param source
     * @param startFlag
     * @param endFlag
     * @return
     */
    public static String extractRecDate(String source, String startFlag, String endFlag) {
        String headerText = getKeyWords(source, startFlag, endFlag, true);
        //标识  通常为 RCV
        String recFlag = headerText.split("[^a-z^A-Z]")[0];
        String recDate = headerText.replace(recFlag, EMPTY_STRING).trim();
        log.info("======头部标识:" + recFlag);
        log.info("======报文接收日期:" + recDate);
        return recDate;
    }

    /**
     * 获取唯一表示
     *
     * @param source
     * @param startFlag
     * @param endFlag
     * @return
     */
    public static String extractGuid(String source, String startFlag, String endFlag) {
        String guid = getKeyWords(source, startFlag, endFlag, true);
        log.info("======唯一标识:" + guid);
        return guid;
    }

    /**
     * 获取电报等级
     *
     * @param source
     * @param startFlag
     * @param endFlag
     * @return
     */
    public static String extractPriority(String source, String startFlag, String endFlag) {
        String priority = getKeyWords(source, startFlag, endFlag, true);
        log.info("======电报等级:" + priority);
        return priority;
    }

    /**
     * 获取收电地址
     *
     * @param source
     * @param startFlag
     * @param endFlag
     * @return
     */
    public static String extractDestination(String source, String startFlag, String endFlag, String priority) {
        String destinationText = getKeyWords(source, startFlag, endFlag, false);
        String destination = "";
        String begin = "";
        String end = "";
        int firstPoint = destinationText.indexOf(DECIMAL_POINT);
        int lastPoint = destinationText.lastIndexOf(DECIMAL_POINT);
        //仅清除首尾的换行符
        destinationText = StringUtils.trim(destinationText.toCharArray()).trim();
        if (lastPoint > -1 || firstPoint > -1) {
            //存在详细收电地址信息
            begin = priority + BLANK_SPACE + destinationText.substring(0, firstPoint);
            end = destinationText.substring(lastPoint);
            destination = begin + end;

        } else {
            destination = priority + BLANK_SPACE + destinationText;
        }
        //去掉前面三位电报等级的内容
        destination = destination.substring(2, destination.length()).trim();
        log.info("======收电地址:" + destination);
        return destination;
    }

    /**
     * 获取发电地址
     *
     * @param source
     * @param startFlag
     * @param endFlag
     * @return
     */
    public static Pair<String, String> extractOrigin(String source, String startFlag, String endFlag) {
        String origin = getKeyWords(source, startFlag, endFlag, true);
        String[] sdINfo = origin.trim().split(BLANK_SPACE);
        String originText = sdINfo[0];
        String sendTime = sdINfo[1];
        log.info("======发电地址:" + originText);
        log.info("======发电时间:" + sendTime);
        return Pair.makePair(originText, sendTime);
    }

    /**
     * 提取报文内容
     *
     * @param source
     * @param startFlag
     * @param endFlag
     * @return
     */
    public static String extractText(String source, String startFlag, String endFlag) {
        String text = StringUtils.trim(getKeyWords(source, startFlag, endFlag, false).toCharArray());
        log.info("======报文内容:" + JSON.toJSONString(text));

        return text;
    }


    /**
     * 用于提取KeyWords 中间内容的公共方法
     *
     * @param source
     * @param startFlag
     * @param endFlag
     * @param clearLineFeed
     * @return
     */
    public static String getKeyWords(String source, String startFlag, String endFlag, boolean clearLineFeed) {
        try {
            int startIndex = source.indexOf(startFlag);
            if (startIndex == -1) {
                //将对应节点未找到的异常 抛出
                switch (startFlag) {
                    case START_FLAG_HEADER:
                        throw new ExtractNodeNotFind(ResponseCodeEnum.HEADER_NODE_NOT_FIND);
                    case START_FLAG_PRIORITY:
                        throw new ExtractNodeNotFind(ResponseCodeEnum.PRIORITY_NODE_NOT_FIND);
                    case START_FLAG_GUID:
                        throw new ExtractNodeNotFind(ResponseCodeEnum.GUID_NODE_NOT_FIND);
                    case START_FLAG_ORIGIN:
                        throw new ExtractNodeNotFind(ResponseCodeEnum.ORIGIN_NODE_NOT_FIND);
                    case START_FLAG_DESTINATION:
                        throw new ExtractNodeNotFind(ResponseCodeEnum.DESTINATION_NODE_NOT_FIND);
                    case START_FLAG_TEXT:
                        throw new ExtractNodeNotFind(ResponseCodeEnum.TEXT_NODE_NOT_FIND);
                }
            }
            int fromIndex = source.indexOf(startFlag) + startFlag.length();
            int endIndex = source.indexOf(endFlag, fromIndex);
            String specifyText = source.substring(fromIndex, endIndex);
            String result = clearLineFeed ? specifyText.replaceAll(LINE_FEED, EMPTY_STRING) : specifyText;

            return result;
        } catch (Exception e) {
            if (!(e instanceof ExtractNodeNotFind)) {
                //异常抛出时 精确到具体错误节点
                switch (startFlag) {
                    case START_FLAG_HEADER:
                        throw new ExtractHeaderFailure(ResponseCodeEnum.EXTRACT_HEADER_FAILURE);
                    case START_FLAG_PRIORITY:
                        throw new ExtractPriorityFailure(ResponseCodeEnum.EXTRACT_PRIORITY_FAILURE);
                    case START_FLAG_GUID:
                        throw new ExtractGUIDFailure(ResponseCodeEnum.EXTRACT_GUID_FAILURE);
                    case START_FLAG_ORIGIN:
                        throw new ExtractOriginFailure(ResponseCodeEnum.EXTRACT_ORIGIN_FAILURE);
                    case START_FLAG_DESTINATION:
                        throw new ExtractDestinationFailure(ResponseCodeEnum.EXTRACT_DESTINATION_FAILURE);
                    case START_FLAG_TEXT:
                        throw new ExtractTextFailure(ResponseCodeEnum.EXTRACT_TEXT_FAILURE);
                }
            }
            //未知情况的异常 和 节点未找到的异常 直接抛出即可
            throw e;
        }
    }


}
